use async_nats::Client;
use serde::{Deserialize, Serialize};
use anyhow::Result;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EntityEvent {
    pub entity_type: String,
    pub entity_id: String,
    pub event_type: EventType,
    pub data: serde_json::Value,
    pub timestamp: i64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum EventType {
    Created,
    Updated,
    Deleted,
    StatusChanged,
}

pub struct EventPublisher {
    client: Client,
}

impl EventPublisher {
    pub fn new(client: Client) -> Self {
        Self { client }
    }

    pub async fn publish_transport_plan_event(
        &self,
        entity_id: &str,
        event_type: EventType,
        data: serde_json::Value,
    ) -> Result<()> {
        let event = EntityEvent {
            entity_type: "transport_plan".to_string(),
            entity_id: entity_id.to_string(),
            event_type,
            data,
            timestamp: chrono::Utc::now().timestamp(),
        };

        let payload = serde_json::to_vec(&event)?;
        self.client
            .publish("tms.transport_plan.events", payload.into())
            .await?;

        Ok(())
    }

    pub async fn publish_vehicle_event(
        &self,
        entity_id: &str,
        event_type: EventType,
        data: serde_json::Value,
    ) -> Result<()> {
        let event = EntityEvent {
            entity_type: "vehicle".to_string(),
            entity_id: entity_id.to_string(),
            event_type,
            data,
            timestamp: chrono::Utc::now().timestamp(),
        };

        let payload = serde_json::to_vec(&event)?;
        self.client
            .publish("tms.vehicle.events", payload.into())
            .await?;

        Ok(())
    }

    pub async fn publish_order_event(
        &self,
        entity_id: &str,
        event_type: EventType,
        data: serde_json::Value,
    ) -> Result<()> {
        let event = EntityEvent {
            entity_type: "order".to_string(),
            entity_id: entity_id.to_string(),
            event_type,
            data,
            timestamp: chrono::Utc::now().timestamp(),
        };

        let payload = serde_json::to_vec(&event)?;
        self.client
            .publish("tms.order.events", payload.into())
            .await?;

        Ok(())
    }

    pub async fn publish_location_event(
        &self,
        vehicle_id: &str,
        data: serde_json::Value,
    ) -> Result<()> {
        let event = EntityEvent {
            entity_type: "vehicle_location".to_string(),
            entity_id: vehicle_id.to_string(),
            event_type: EventType::Updated,
            data,
            timestamp: chrono::Utc::now().timestamp(),
        };

        let payload = serde_json::to_vec(&event)?;
        self.client
            .publish("tms.vehicle_location.events", payload.into())
            .await?;

        Ok(())
    }
}